package ini类

import (
	"errors"
	时间类 "gitee.com/go_888/extends/carbon"
	转换类 "gitee.com/go_888/extends/goframe/gconv"
	文件类 "gitee.com/go_888/extends/goframe/gfile"
	文本类 "gitee.com/go_888/extends/goframe/gstr"

	"gitee.com/go_888/internal-call/ini.v1"
	"log"
	"time"
)

type X配置项 struct {
	父类 ini.File
}

// X创建 从指定的INI文件创建一个X配置项对象。
// ini文件 参数是INI文件的路径。
// 忽略大小写 可选参数，指定是否忽略配置项的大小写，默认为false,
func X创建(ini路径 string, 忽略大小写 ...bool) (*X配置项, error) {
	//如果配置文件不存在, 则创建一个.
	if !文件类.X是否存在文件(ini路径) {
		log.Println("创建配置项() 错误,文件不存在:" + ini路径)
		return &X配置项{}, errors.New("创建配置项() 错误,文件不存在:" + ini路径)
	}

	// 默认忽略大小写
	忽略大小写2 := false
	if len(忽略大小写) > 0 {
		忽略大小写2 = 忽略大小写[0]
	}

	// 根据忽略大小写2的值，选择合适的加载方式
	if 忽略大小写2 {
		// 使用忽略大小写的方式加载INI文件
		cfg, err := ini.InsensitiveLoad(ini路径)
		if err != nil {
			return &X配置项{}, err
		}
		return &X配置项{*cfg}, nil
	} else {
		// 使用普通方式加载INI文件
		cfg, err := ini.Load(ini路径)
		if err != nil {
			return &X配置项{}, err
		}
		return &X配置项{*cfg}, nil
	}
}

// X创建配置项并从文本根据给定的文本配置创建一个X配置项实例。
// 文本配置 要解析的配置文本。
// 忽略大小写 可选参数，指定是否忽略配置项的大小写，默认为false
func X创建并从文本(文本配置 string, 忽略大小写 ...bool) (*X配置项, error) {
	// 默认忽略大小写
	忽略大小写2 := false
	if len(忽略大小写) > 0 {
		忽略大小写2 = 忽略大小写[0]
	}
	if 忽略大小写2 {
		// 使用不区分大小写的加载方式
		cfg, err := ini.InsensitiveLoad(转换类.X取字节集(文本配置)) //ini.v1需要转换成字节集才会识别是直接传递数据.
		if err != nil {
			return &X配置项{}, err
		}
		return &X配置项{*cfg}, nil
	} else {
		// 使用区分大小写的加载方式
		cfg, err := ini.Load(转换类.X取字节集(文本配置)) //ini.v1需要转换成字节集才会识别是直接传递数据.
		if err != nil {
			return &X配置项{}, err
		}
		return &X配置项{*cfg}, nil
	}
}

// X取文本值 用于从配置项中获取指定项和名称的键的文本值。
// 如果提供了默认值，则在键值不存在或获取失败时返回默认值；
// 否则，在键值不存在或获取失败时返回空字符串。
// 参数:
// 节名 - 配置文件中的项名称。
// 名称 - 配置项中的键名称。
// 默认值 - 可选参数，用于指定键值不存在或获取失败时的默认返回值。
// 返回值:
// 返回指定项、名称的键的文本值，如果键不存在或获取失败，则返回默认值或空字符串。
func (this *X配置项) X取文本值(节名, 名称 string, 默认值 ...string) string {
	if len(默认值) > 0 {
		// 当提供了默认值时，使用MustString方法尝试获取键的文本值，
		// 如果获取失败则返回默认值[0]。
		return this.父类.Section(节名).Key(名称).MustString(默认值[0])
	} else {
		// 当未提供默认值时，使用String方法尝试获取键的文本值，
		// 如果获取失败则返回空字符串。
		return this.父类.Section(节名).Key(名称).String()
	}
}

// X取布尔值 根据给定的节名和名称，从配置项中获取对应的布尔值。
// 该方法利用父类配置项的方法，定位到特定的配置节和配置项，并尝试将其值转换为布尔类型。
// 如果转换成功，则返回布尔值和nil错误；如果转换失败，则返回false和相应的错误信息。
// 参数:
// 节名 - 配置节的名称。
// 名称 - 配置项的名称。
// 返回值:
// bool - 转换为布尔类型的配置项值。
// error - 如果转换失败，返回错误信息。
func (this *X配置项) X取布尔值(节名, 名称 string) (bool, error) {
	return this.父类.Section(节名).Key(名称).Bool()
}

// X取整数 根据指定的项和名称从配置项中获取一个整数值。
// 如果项或名称对应的颜色值不存在或者无法转换为整数，则返回默认值（如果提供）。
// 参数:
// 节名: 配置文件中的节名。
// 名称: 配置文件中的键名。
// 默认值: 可选参数，用于指定在无法找到或转换配置值时返回的默认整数值。
// 返回值:
// 整数类型: 从配置文件中获取或通过默认值推导出的整数值。
// error: 在转换过程中可能出现的错误，如果成功则返回nil。
func (this *X配置项) X取整数(节名, 名称 string, 默认值 ...int) (int, error) {
	// 当提供了默认值时，使用MustInt方法尝试将配置项中的值转换为整数，如果转换失败则使用默认值。
	if len(默认值) > 0 {
		return this.父类.Section(节名).Key(名称).MustInt(默认值[0]), nil
	} else {
		// 当没有提供默认值时，直接尝试获取配置项中的整数值。
		return this.父类.Section(节名).Key(名称).Int()
	}
}

// X取整数64位 从配置项中获取一个64位整数值。
// 该方法首先尝试从指定的项和名对应的配置项中获取一个64位整数值。
// 如果提供了默认值，则在获取失败时返回默认值；否则，返回获取到的值或错误。
// 参数:
// 节名 - 配置项的项部分。
// 名称 - 配置项的名部分。
// 默认值 - 可选参数，用于指定在获取配置项失败时返回的默认值。
// 返回值:
// int64 - 获取到的64位整数值或默认值。
// error - 如果获取失败且未提供默认值，则返回错误。
func (this *X配置项) X取整数64位(节名, 名称 string, 默认值 ...int64) (int64, error) {
	// 如果提供了默认值，使用MustInt64方法，该方法在转换失败时会返回默认值。
	if len(默认值) > 0 {
		return this.父类.Section(节名).Key(名称).MustInt64(默认值[0]), nil
	} else {
		// 如果没有提供默认值，使用Int64方法，该方法在转换失败时会返回错误。
		return this.父类.Section(节名).Key(名称).Int64()
	}
}

// X取正整数 从配置项中获取一个正整数值。
// 如果提供了默认值，则在配置中的值无法转换为正整数时返回默认值。
// 参数:
// 节名: 配置文件中的节名称。
// 名称: 要获取的配置项的名称。
// 默认值: 一个可选的默认值列表，如果配置项不存在或无法转换为正整数，则使用该默认值。
// 返回值:
// uint: 配置项的正整数值，如果提供了默认值且配置项不存在或无法转换，则返回默认值。
// error: 如果发生错误（例如，配置项存在但无法转换为正整数且未提供默认值），则返回错误信息。
func (this *X配置项) X取正整数(节名, 名称 string, 默认值 ...uint) (uint, error) {
	// 如果提供了默认值
	if len(默认值) > 0 {
		// 使用MustUint方法，当转换失败时，会返回默认值，但不返回错误
		return this.父类.Section(节名).Key(名称).MustUint(默认值[0]), nil
	} else {
		// 直接使用Uint方法尝试转换，当转换失败且未提供默认值时，会返回错误
		return this.父类.Section(节名).Key(名称).Uint()
	}
}

// X取正整数64位 从配置项中获取一个无符号64位整数值。
// 该方法首先尝试在指定的项和名下获取值，如果未提供默认值，则返回可能的错误。
// 如果提供了默认值，则在转换失败时返回该默认值，不触发错误。
// 参数:
// 节名: 配置文件中的节名称。
// 名称: 配置项的键名称。
// 默认值: 一个可选的默认值列表，如果转换失败，将返回该值。
// 返回值:
// uint64: 成功转换后的无符号64位整数值，或提供的默认值。
// error: 如果转换失败且未提供默认值，则返回错误；否则不返回错误。
func (this *X配置项) X取正整数64位(节名, 名称 string, 默认值 ...uint64) (uint64, error) {
	// 检查是否提供了默认值，如果提供了，默认值存在于切片的第一个位置。
	if len(默认值) > 0 {
		// 使用MustUint64方法，该方法在转换失败时会返回默认值，避免错误。
		return this.父类.Section(节名).Key(名称).MustUint64(默认值[0]), nil
	} else {
		// 直接尝试获取无符号64位整数值，可能返回实际值或错误。
		return this.父类.Section(节名).Key(名称).Uint64()
	}
}

// X取小数64位 从配置项中获取一个浮点数值。
// 节名: 配置文件中的节名。
// 名称: 配置项的键名。
// 默认值: 用于在未找到键或转换失败时返回的默认值。
// 返回值:
// float64: 配置项对应的浮点数值，如果提供了默认值且未找到键或转换失败，则返回默认值。
// error: 如果未提供默认值且未找到键或转换失败，则返回错误信息。
func (this *X配置项) X取小数64位(节名, 名称 string, 默认值 ...float64) (float64, error) {
	// 当提供了默认值时，使用MustFloat64方法尝试获取并转换配置项为float64，如果失败则返回默认值。
	if len(默认值) > 0 {
		return this.父类.Section(节名).Key(名称).MustFloat64(默认值[0]), nil
	} else {
		// 当未提供默认值时，使用Float64方法尝试获取配置项的float64值，如果失败则返回错误。
		return this.父类.Section(节名).Key(名称).Float64()
	}
}

// X取Gosdk时间 从配置项中获取指定项和名的时间值。
// 如果提供了默认值，则在无法获取时间值时返回默认值。
// 如果没有提供默认值，则在无法获取时间值时返回time.Time的零值。
// 参数:
// 节名: 配置文件中的部分或节名称。
// 名称: 配置项的键名。
// 默认值: 一个可选的时间默认值列表。
// 返回值:
// time.Time: 获取到的时间值或默认值。
// error: 如果发生错误则返回错误信息，否则返回nil。
func (this *X配置项) X取Gosdk时间(节名, 名称 string, 默认值 ...time.Time) (*time.Time, error) {
	//这里改用gf的时间类解析,可以支持更多的格式.
	时间对象 := 时间类.X解析文本时间(this.X取文本值(节名, 名称))
	返回值 := 时间对象.X取Gosdk时间()
	if 时间对象.X是否有错误() {
		if len(默认值) > 0 {
			return &默认值[0], nil
		}
		return nil, 时间对象.X错误
	} else {
		return &返回值, nil
	}
}
func (this *X配置项) X取时间类(节名, 名称 string, 默认值 ...时间类.Carbon) (*时间类.Carbon, error) {
	//这里改用gf的时间类解析,可以支持更多的格式.
	时间对象 := 时间类.X解析文本时间(this.X取文本值(节名, 名称))

	if 时间对象.X是否有错误() {
		if len(默认值) > 0 {
			return &默认值[0], nil
		}
		return nil, 时间对象.X错误
	} else {
		return 时间对象, nil
	}
}

// X取文本数组 从配置项中获取一个字符串数组值。
// 这个方法首先定位到配置文件中的特定项和键，然后使用指定的分隔符将字符串分割成数组返回。
// 参数:
// 节名: 配置文件中的项名称，用于定位需要读取的配置。
// 名称: 配置项中的键名称，用于定位具体的配置值。
// 分隔符: 用于将获取到的字符串按照指定的分隔符分割成数组。
// 返回值:
// []string: 返回一个字符串数组，包含按照分隔符分割后的各个字符串。
func (this *X配置项) X取文本数组(节名, 名称, 分隔符 string) []string {
	return this.父类.Section(节名).Key(名称).Strings(分隔符)
}

// X取整数数组 根据给定的项和名称，从配置文件中获取一个整数数组。
// 这个方法首先通过项和名称定位到配置文件中的特定部分，然后使用指定的分隔符将配置值解析为一个整数数组。
// 参数:
// 节名: 配置文件中的节（section）名称，用于定位配置项。
// 名称: 配置项的名称，用于定位特定的配置值。
// 分隔符: 用于分割配置值字符串的分隔符。
// 返回值:
// []int: 解析后的整数数组。
func (this *X配置项) X取整数数组(节名, 名称 string, 分隔符 string) []int {
	return this.父类.Section(节名).Key(名称).Ints(分隔符)
}

// X取整数64位数组  根据给定的项和名称，从配置文件中获取一个64位整数数组。
// 该方法首先定位到配置文件中的指定项和键，然后使用指定的分隔符将键的值分割成一个64位整数数组。
// 参数:
// 节名: 配置文件中的节名。
// 名称: 配置文件中的键名。
// 分隔符: 分割键值时使用的分隔符。
// 返回值:
// 返回一个64位整数数组，如果获取失败则返回空数组。
func (this *X配置项) X取整数64位数组(节名, 名称 string, 分隔符 string) []int64 {
	return this.父类.Section(节名).Key(名称).Int64s(分隔符)
}

// X取正整数数组 从配置项中获取一个正整数数组。
// 该方法首先通过项和名定位到配置文件中的特定部分和键，
// 然后使用指定的分隔符将配置值解析为正整数数组。
// 参数:
// 节名: 配置文件中的部分（section）名称。
// 名称: 配置键（key）的名称。
// 分隔符: 用于分割配置值字符串的分隔符。
// 返回值:
// []uint: 一个包含正整数的数组。
func (this *X配置项) X取正整数数组(节名, 名称 string, 分隔符 string) []uint {
	return this.父类.Section(节名).Key(名称).Uints(分隔符)
}

// X取正整数64位数组 根据指定的节名、配置项名称和分隔符，获取配置项的64位正整数数组值。
// 该方法首先通过父类的Section方法定位到指定的配置节，
// 然后通过Key方法定位到指定名称的配置项，
// 最后使用Uint64s方法将配置项的值解析为一个64位正整数数组。
// 参数：
// 节名: 配置文件中的节名称，用于定位配置项。
// 名称: 配置项的名称，用于定位特定的配置项。
// 分隔符: 用于分割配置项值的字符串，以便将其解析为数组。
// 返回值：
// []uint64: 配置项的64位正整数数组值。
func (this *X配置项) X取正整数64位数组(节名, 名称 string, 分隔符 string) []uint64 {
	return this.父类.Section(节名).Key(名称).Uint64s(分隔符)
}

// X取小数64位数组 根据指定的节名、名称和分隔符，获取配置文件中的64位小数数组。
// 该方法是X配置项类的一个成员方法，主要用于解析配置文件中特定节和键的值，
// 并根据指定的分隔符将这些值解析为一个64位小数数组。
// 参数:
// 节名: 配置文件中的节名，用于定位特定的配置项。
// 名称: 配置项的键名，用于定位特定的配置值。
// 分隔符: 用于分割配置值字符串的分隔符，通常是配置文件中该配置项值的自然分隔符。
// 返回值:
// []float64: 解析后的64位小数数组。
func (this *X配置项) X取小数64位数组(节名, 名称 string, 分隔符 string) []float64 {
	return this.父类.Section(节名).Key(名称).Float64s(分隔符)
}

// X取go时间数组 根据给定的节名和键名，从配置中取出一个时间数组。
// 此方法演示了如何使用分隔符解析配置文件中的时间数组。
// 参数:
// 节名: 配置文件中的节名，字符串类型。
// 名称: 配置文件中的键名，字符串类型。
// 分隔符: 用于分割时间字符串的分隔符，字符串类型。
// 返回值:
// 返回一个时间数组，如果配置中不存在指定的节或键，则返回空数组。
func (this *X配置项) X取go时间数组(节名, 名称 string, 分隔符 string) []time.Time {
	//这里改用gf的时间类解析,可以支持更多的文本格式.
	返回数组 := []time.Time{}
	文本数组 := this.X取文本数组(节名, 名称, 分隔符)
	for i := range 文本数组 {
		待转换 := 时间类.X解析文本时间(文本数组[i])
		if 待转换.X是否有错误() == false {
			返回数组 = append(返回数组, 待转换.X取Gosdk时间())
		}
	}
	return 返回数组
}
func (this *X配置项) X取时间类数组(节名, 名称 string, 分隔符 string) []*时间类.Carbon {
	//这里改用gf的时间类解析,可以支持更多的文本格式.
	返回数组 := []*时间类.Carbon{}
	文本数组 := this.X取文本数组(节名, 名称, 分隔符)
	for i := range 文本数组 {
		待转换 := 时间类.X解析文本时间(文本数组[i])
		if 待转换.X是否有错误() == false {
			返回数组 = append(返回数组, 待转换)
		}
	}
	return 返回数组
}

// X设置值 在配置项的特定节中设置键的值。
// 此方法允许动态更新配置项中的值，而不必重启应用程序。
// 参数:
// 节名: 要修改的配置节的名称。
// 名称: 要设置的键的名称。
// 值: 要为键设置的新值。
func (this *X配置项) X设置值(节名, 名称 string, 值 string) {
	this.父类.Section(节名).Key(名称).SetValue(值)
}

// X保存 将当前配置项的属性保存到指定的文件中。
// 这个方法通过调用父类的SaveTo方法实现保存操作。
// 参数:
// 文件名 - 要保存配置的文件路径。
// 返回值:
// 如果保存过程中发生错误，则返回错误信息；否则返回nil。
func (this *X配置项) X保存(ini路径 string) error {
	return this.父类.SaveTo(ini路径)
}

// X取所有名称 根据给定的节名，返回该节中所有键的名称
// 该方法属于X配置项类型，用于操作特定配置节内的键
// 参数:
// 节名 - 配置文件中的节名称，用于指定哪个节的键需要获取
// 返回值:
// []string - 返回一个字符串切片，包含指定节内所有键的名称
func (this *X配置项) X取所有名称(节名 string) []string {
	// 调用父类的Section方法获取指定节，并通过KeyStrings方法获取该节内所有键的名称
	返回值 := this.父类.Section(节名).KeyStrings()
	return 返回值
}

// X取所有值 根据给定的节名，返回该节下所有键的键值对
// 此方法特定于配置项对象，用于访问配置文件中特定节的所有键值
// 参数:
// 节名 string: 配置文件中的节名称，用于指定需要获取键值对的节
// 返回值:
// map[string]string: 一个映射，包含了指定节下的所有键值对，键为配置项名称，值为配置项的值
func (this *X配置项) X取所有值(节名 string) map[string]string {
	// 调用父类的Section方法获取指定节名的配置项，并通过KeysHash方法获取该节下所有键的键值对
	返回值 := this.父类.Section(节名).KeysHash()
	return 返回值
}
func (this *X配置项) X取所有节名() []string {
	// 调用父类的Section方法获取指定节名的配置项，并通过KeysHash方法获取该节下所有键的键值对
	返回值 := this.父类.SectionStrings()
	新返回值 := []string{}
	for _, s := range 返回值 {
		//去除默认节名称
		if 文本类.X到小写(s) != "default" {
			新返回值 = append(新返回值, 文本类.X删首尾空与字符(s))
		}
	}
	return 新返回值
}
func (this *X配置项) X删除节名(节名 string) {
	this.父类.DeleteSection(节名)
}
